﻿using System.Globalization;
using System.Runtime.InteropServices;

namespace Microsoft.Xna.Framework.Graphics
{
    /// <summary>
    /// 	Describes a custom vertex format structure that contains position, normal data, and color information.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct VertexPositionNormalColor : IVertexType
    {
        #region Static Operations

        /// <summary>
        /// 	Vertex declaration, which defines per-vertex data.
        /// </summary>
        public static readonly VertexDeclaration VertexDeclaration;

        static VertexPositionNormalColor()
        {
            var elements = new[]
                               {
                                   new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0), new VertexElement(24, VertexElementFormat.Color, VertexElementUsage.Color, 0)
                               };
            VertexDeclaration = new VertexDeclaration(elements);
        }

        /// <summary>
        /// 	Compares two objects to determine whether they are the same.
        /// </summary>
        /// <returns> true if the objects are the same; false otherwise. </returns>
        /// <param name="left"> Object to the left of the equality operator. </param>
        /// <param name="right"> Object to the right of the equality operator. </param>
        public static bool operator ==(VertexPositionNormalColor left, VertexPositionNormalColor right)
        {
            return left.Position == right.Position && left.Normal == right.Normal && left.Color == right.Color;
        }

        /// <summary>
        /// 	Compares two objects to determine whether they are different.
        /// </summary>
        /// <returns> true if the objects are different; false otherwise. </returns>
        /// <param name="left"> Object to the left of the inequality operator. </param>
        /// <param name="right"> Object to the right of the inequality operator. </param>
        public static bool operator !=(VertexPositionNormalColor left, VertexPositionNormalColor right)
        {
            return !(left == right);
        }

        #endregion

        #region Fields & Properties

        /// <summary>
        /// 	XYZ position.
        /// </summary>
        public Vector3 Position;

        /// <summary>
        /// 	XYZ surface normal.
        /// </summary>
        public Vector3 Normal;

        /// <summary>
        /// 	The vertex color.
        /// </summary>
        public Color Color;

        #endregion

        #region Constructors

        /// <summary>
        /// 	Initializes a new instance of the VertexPositionNormalTexture class.
        /// </summary>
        /// <param name="position"> Position of the vertex. </param>
        /// <param name="normal"> The vertex normal. </param>
        /// <param name="color"> The color of the vertex. </param>
        public VertexPositionNormalColor(Vector3 position, Vector3 normal, Color color)
        {
            Position = position;
            Normal = normal;
            Color = color;
        }

        #endregion

        #region Implementation of IVertexType

        /// <summary>
        /// 	Gets a vertex declaration.
        /// </summary>
        VertexDeclaration IVertexType.VertexDeclaration
        {
            get
            {
                return VertexDeclaration;
            }
        }

        #endregion

        #region Overrides of ValueType

        /// <summary>
        /// 	Gets the hash code for this instance.
        /// </summary>
        /// <returns> Hash code for this object. </returns>
        public override int GetHashCode()
        {
            return Position.GetHashCode() ^ Normal.GetHashCode() ^ Color.GetHashCode();
        }

        /// <summary>
        /// 	Retrieves a string representation of this object.
        /// </summary>
        /// <returns> String representation of this object. </returns>
        public override string ToString()
        {
            return string.Format(CultureInfo.CurrentCulture, "{{Position:{0} Normal:{1} Color:{2}}}", Position, Normal, Color);
        }

        /// <summary>
        /// 	Returns a value that indicates whether the current instance is equal to a specified object.
        /// </summary>
        /// <returns> true if the objects are the same; false otherwise. </returns>
        /// <param name="obj"> The <see cref="T:System.Object" /> to compare with the current <see
        ///  	cref="T:Microsoft.Xna.Framework.Graphics.VertexPositionNormalTexture" /> . </param>
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }
            if (obj.GetType() != GetType())
            {
                return false;
            }
            return this == (VertexPositionNormalColor)obj;
        }

        #endregion
    }
}